import json

from carts.utils import merge_cookie_redis_cart
from django.contrib.auth import login, authenticate
from django.shortcuts import render, redirect
from QQLoginTool.QQtool import OAuthQQ
from django.conf import settings
from django import http
from django.views.generic import View
from django_redis import get_redis_connection

from meiduo_mall.utils import sinaweibopy3
from oauth.models import OAuthQQUser, OAuthSinaUser
from oauth.utils import decode_openid
from users.models import User
from . import utils
from meiduo_mall.utils import sinaweibopy3
from meiduo_mall.utils import constants


class QQLoginView(View):
    def get(self, request):
        # 1 获取参数
        state = request.GET.get('next', '/')

        oath_qq = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,
                          redirect_uri=settings.QQ_REDIRECT_URI, state=state)
        qq_url = oath_qq.get_qq_url()

        return http.JsonResponse({'login_url': qq_url})


class OAuthCallBack(View):
    def get(self, request):
        # 1.获取参数
        code = request.GET.get('code')
        state = request.GET.get('state', '/')

        if not code:
            return http.HttpResponseForbidden('code丢失')

        oath_qq = OAuthQQ(client_id=settings.QQ_CLIENT_ID, client_secret=settings.QQ_CLIENT_SECRET,
                          redirect_uri=settings.QQ_REDIRECT_URI, state=state)

        # 获取access-token
        token = oath_qq.get_access_token(code=code)
        # 获取openid
        open_id = oath_qq.get_open_id(access_token=token)

        # 判断用户是否已绑定
        try:
            oath_qq_user = OAuthQQUser.objects.get(open_id=open_id)
        except Exception:
            # 初次授权
            # 加密opend_id
            open_id = utils.encode_openid(open_id)
            content = {'token': open_id}
            return render(request, 'oauth_callback.html', content)
        else:
            # 非初次授权，获取美多用户
            user = oath_qq_user.user
            # 状态保持
            login(request, user)
            # 重定向到主页
            rsp = redirect('/')
            rsp.set_cookie('username', user.username)
            # 合并购物车
            rsp = merge_cookie_redis_cart(request, rsp, user)
            return rsp

    def post(self, request):
        # 获取参数
        data = request.POST
        mobile = data.get('mobile')
        pwd = data.get('pwd')
        sms_code = data.get('sms_code')
        open_id = request.POST.get('access_token')

        # 检验参数
        if not all([mobile, pwd, sms_code, open_id]):
            return http.HttpResponseForbidden('参数不全')

        # 检验openid
        open_id = decode_openid(open_id)
        if not open_id:
            return http.HttpResponseForbidden('openid已过期')

        # 短信验证码校验
        redis_conn = get_redis_connection('verify_code')
        redis_phone_code = redis_conn.get('sms_code_%s' % mobile)
        if redis_phone_code == None:
            return render(request, 'register.html', {'error_sms_msg': '手机验证码已过期'})

        if redis_phone_code.decode() != sms_code:
            return render(request, 'register.html', {'error_sms_msg': '手机验证码错误'})

        user = authenticate(request, username=mobile, password=pwd)

        if not user:
            user = User.objects.create_user(username=mobile, password=pwd, mobile=mobile)

        # 创建user授权对象
        oauth_qq_user = OAuthQQUser()
        oauth_qq_user.user = user
        oauth_qq_user.open_id = open_id
        # 数据入库
        oauth_qq_user.save()
        # 状态保持
        login(request, user)
        # 返回响应
        rsp = redirect('/')
        rsp.set_cookie('username', mobile)
        rsp = merge_cookie_redis_cart(request, rsp, user)
        return rsp


class SinaCallback(View):
    def get(self, request):
        return render(request, 'sina_callback.html')


class SinaLoginView(View):
    def get(self, request):
        client = sinaweibopy3.APIClient(app_key=settings.APP_KEY, app_secret=settings.APP_SECRET,
                                        redirect_uri=settings.REDIRECT_URL)
        login_url = client.get_authorize_url()

        return http.JsonResponse({"login_url": login_url})


class OAuthSinaView(View):
    def get(self, request):
        code = request.GET.get('code')

        if not code:
            return http.JsonResponse({'errormsg': '参数不全'}, status=400)

        client = sinaweibopy3.APIClient(app_key=settings.APP_KEY, app_secret=settings.APP_SECRET,
                                        redirect_uri=settings.REDIRECT_URL)
        result = client.request_access_token(code)
        # 获取access_token 新浪的标识符
        access_token = result.access_token

        redis_conn = get_redis_connection('verify_code')

        redis_conn.setex(access_token, constants.SINA_CODE_EXIST_TIME, code)

        try:
            sina = OAuthSinaUser.objects.get(access_token=access_token)
            user = sina.user
            content = {
                'user_id': user.id
            }
            login(request, user)
            rsp = http.JsonResponse(content)
            rsp.set_cookie('username', user.username)
            return rsp
        except:
            return http.JsonResponse({'access_token': access_token})

    def post(self, request):
        data_dict = json.loads(request.body.decode())
        password = data_dict.get('password')
        mobile = data_dict.get('mobile')
        sms_code = data_dict.get('sms_code')
        access_token = data_dict.get('access_token')

        # 检验参数
        if not all([mobile, password, sms_code, access_token]):
            return http.HttpResponseForbidden('参数不全')

        # 检验access_token
        redis_conn = get_redis_connection('verify_code')
        code = redis_conn.get(access_token)

        if not code:
            return http.HttpResponseForbidden('access_token已过期')

        # 短信验证码校验
        redis_conn = get_redis_connection('verify_code')
        redis_phone_code = redis_conn.get('sms_code_%s' % mobile)
        if redis_phone_code == None:
            return render(request, 'register.html', {'error_sms_msg': '手机验证码已过期'})

        if redis_phone_code.decode() != sms_code:
            return render(request, 'register.html', {'error_sms_msg': '手机验证码错误'})

        user = authenticate(request, username=mobile, password=password)
        if not user:
            user = User.objects.create(
                username=mobile,
                password=password,
                mobile=mobile,
            )
        OAuthSinaUser.objects.create(user=user, access_token=access_token)
        login(request, user)
        rsp = http.JsonResponse({})
        rsp.set_cookie('username', user.username)
        return rsp
